<?php declare(strict_types=1);

/**
 * @author      guosir
 * @copyright   2023-2025 owner
 **/

namespace Srv\Apps\Apis\Order\Ctl;

use Srv\Apps\Proto\DTO\Order\PayTplAddDTO;
use Srv\Apps\Proto\DTO\Order\PayTplEditDTO;
use Srv\Apps\Proto\DTO\Order\PayTplListDTO;
use Srv\Apps\Proto\Enum\PayTplDefaultShowEnum;
use Srv\Apps\Proto\Enum\PlatformEnum;
use Srv\Apps\Proto\Enum\YesOrNoEnum;
use Srv\Apps\Proto\VO\Order\PayTplListVO;
use Srv\Apps\Proto\VO\Order\PayTplVO;
use Srv\Libs\Common\CommArray;
use Srv\Libs\Common\CommJson;
use Srv\Libs\Common\CommTime;
use Srv\Libs\Frame\ControllerAbstract;
use Srv\Libs\Frame\Page;
use Srv\Libs\Storage\DataMysql;

final class PayTplCtl extends ControllerAbstract
{
    private ?DataMysql $DbAuto              = null;     // DB-Write

    /**
     * @return static
     * tag
     */
    final public static function tag():self
    {
        $thisObject                         = self::tagGet();
        if($thisObject instanceof self){
            $thisObject->DbAuto             = self::getDbAuto();
        }
        return $thisObject;
    }

    /**
     * @param int $tppdId
     * @return array
     * getPayTplSrc
     */
    public function getPayTplSrc(int $tppdId):array
    {
        if($tppdId < 1) return [];
        $isFail         = false;
        $payTplRecord   = $this->DbAuto->getDataOne('SELECT tppd_id, tppd_platform, tppd_name, pgsp_ids, tppd_default_show, tppd_default, tppd_first, tppd_create_time, tppd_update_time FROM '.$this->DbAuto->getTableNameAll('tpl_paid_conf').' WHERE tppd_id='.$tppdId.' AND tppd_delete=0', $isFail);
        if($isFail || !isset($payTplRecord['tppd_id'])) return [];
        return $payTplRecord;
    }

    /**
     * @param array $tppdIdList
     * @return array
     * getPayTplSrcBatch
     */
    public function getPayTplSrcBatch(array $tppdIdList):array
    {
        if(count($tppdIdList) < 1) return [];
        $isFail     = false;
        $list       = $this->DbAuto->getData('SELECT tppd_id, tppd_platform, tppd_name, pgsp_ids, tppd_default_show, tppd_default, tppd_first, tppd_create_time, tppd_update_time FROM '.$this->DbAuto->getTableNameAll('tpl_paid_conf').' WHERE tppd_id IN('.implode(',', $tppdIdList).') AND tppd_delete=0', $isFail);
        if($isFail || count($list) < 1) return [];
        $listData   = [];
        foreach ($list as $item){
            $tppdIdItem             = intval($item['tppd_id']??0);
            if($tppdIdItem < 1) continue;
            $listData[$tppdIdItem]  = $item;
        }
        return $listData;
    }

    /**
     * @param int $tppdId
     * @return PayTplVO|null
     * getPayTpl
     */
    public function getPayTpl(int $tppdId):?PayTplVO
    {
        $payTplRecord   = $this->getPayTplSrc($tppdId);
        if(!isset($payTplRecord['tppd_id'])) return null;
        return $this->getPayTplVO($payTplRecord);
    }

    /**
     * @param array $tppdIdList
     * @return array
     * getPayTplBatch
     */
    public function getPayTplBatch(array $tppdIdList):array
    {
        $payTplList     = $this->getPayTplSrcBatch($tppdIdList);
        $listData       = [];
        if(CommArray::isForeach($payTplList))foreach ($payTplList as $item){
            $tppdIdItem             = intval($item['tppd_id']??0);
            if($tppdIdItem < 1) continue;
            $listData[$tppdIdItem]  = $this->getPayTplVO($item);
        }
        return $listData;
    }

    /**
     * @param array $payTplRecord
     * @return PayTplVO|null
     * getPayTplVO
     */
    public function getPayTplVO(array $payTplRecord): ?PayTplVO
    {
        $tppdId             = intval($payTplRecord['tppd_id']??0);
        if($tppdId < 1) return null;
        $PayTplVO           = new PayTplVO();
        $PayTplVO->setTppdId($tppdId);
        $PayTplVO->setPlatform(PlatformEnum::parseValue($payTplRecord['tppd_platform']));
        $PayTplVO->setName(trim($payTplRecord['tppd_name']));
        $pgspIdList         = CommJson::decodeArray($payTplRecord['pgsp_ids']??'[]');
        if(count($pgspIdList) > 0){
            $PayGoodsList   = PayCtl::tag()->getPayGoodsBatch($pgspIdList);
            $newList        = [];
            foreach ($pgspIdList as $pgspIdItem){
                $PayGoodsVO = $PayGoodsList[$pgspIdItem]??null;
                if($PayGoodsVO !== null) $newList[] = $PayGoodsVO;
            }
            if(count($newList) > 0)$PayTplVO->setPayGoodsList($newList);
        }
        $PayTplVO->setDefaultShow(PayTplDefaultShowEnum::parseValue($payTplRecord['tppd_default_show']));
        $PayTplVO->setDefault(YesOrNoEnum::parseValue($payTplRecord['tppd_default']));
        $PayTplVO->setFirst(YesOrNoEnum::parseValue($payTplRecord['tppd_first']));
        $PayTplVO->setCreateTime(intval($payTplRecord['tppd_create_time']));
        $PayTplVO->setUpdateTime(intval($payTplRecord['tppd_update_time']));
        return $PayTplVO;
    }

    /**
     * @param Page $Page
     * @param array $whereData
     * @return PayTplListVO|null
     * getPayTplList
     */
    public function getPayTplList(Page $Page, array $whereData): ?PayTplListVO
    {
        $limitString        = $Page->getLimitString();
        $whereString        = ' WHERE tppd_delete=0 ';
        // 检索条件
        if(count($whereData) > 0)foreach ($whereData as $key => $val){
            switch ($key){
                case PayTplListDTO::_tppdId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'tppd_id='. intval($val);
                    break;
                case PayTplListDTO::_platform:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'tppd_platform='. intval($val);
                    break;
                case PayTplListDTO::_name:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'tppd_name LIKE \'%'.$this->DbAuto->getRealEscapeString($val).'%\'';
                    break;
                case PayTplListDTO::_defaultShow:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'tppd_default_show='.intval($val);
                    break;
                case PayTplListDTO::_default:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'tppd_default='.intval($val);
                    break;
                case PayTplListDTO::_first:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'tppd_first='.intval($val);
                    break;
            }
        }
        $isFail             = false;
        $sql                = 'SELECT SQL_CALC_FOUND_ROWS tppd_id, tppd_platform, tppd_name, pgsp_ids, tppd_default_show, tppd_default, tppd_first, tppd_create_time, tppd_update_time FROM '.$this->DbAuto->getTableNameAll('tpl_paid_conf').$whereString.' ORDER BY tppd_id DESC '.$limitString;
        $payTplRecordList   = $this->DbAuto->getData($sql, $isFail);
        $totalNum           = $this->DbAuto->getDataInt('SELECT FOUND_ROWS() as num', 'num');
        if($isFail) return null;
        $PayTplVOList       = [];
        if(CommArray::isForeach($payTplRecordList))foreach($payTplRecordList as $payTplRecord){
            $tppdIdItem     = intval($payTplRecord['tppd_id']);
            if($tppdIdItem < 1) continue;
            $PayTplVO       = $this->getPayTplVO($payTplRecord);
            if(!($PayTplVO instanceof PayTplVO)) continue;
            $PayTplVOList[] = $PayTplVO;
        }
        $PayTplListVO       = new PayTplListVO();
        $PayTplListVO->setList($PayTplVOList);
        $PayTplListVO->setPage($Page->getPageVO($totalNum));
        return $PayTplListVO;
    }

    /**
     * @param array $setData
     * @return int
     * payTplAdd
     */
    public function payTplAdd(array $setData):int
    {
        if(count($setData) < 1) return 0;
        $setString      = '';
        $setDefault     = false;
        foreach ($setData as $key => $val){
            switch ($key){
                case PayTplAddDTO::_platform:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'tppd_platform='.intval($val);
                    break;
                case PayTplAddDTO::_name:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'tppd_name=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case PayTplAddDTO::_pgspIdList:
                    if(!is_array($val) || count($val) < 1) return 0;
                    $payGoodsList   = PayCtl::tag()->getPayGoodsSrcBatch($val);
                    if(count($payGoodsList) < 1) return 0;
                    $psgpIdList     = array_map('intval', array_column($payGoodsList, 'pgsp_id'));
                    $psgpIdList     = array_values(array_intersect($val, $psgpIdList));
                    $pgspIdJson     = CommJson::encodeArray($psgpIdList);
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'pgsp_ids=\''.$this->DbAuto->getRealEscapeString($pgspIdJson).'\'';
                    break;
                case PayTplAddDTO::_defaultShow:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'tppd_default_show='.intval($val);
                    break;
                case PayTplAddDTO::_default:
                    if(YesOrNoEnum::YES_OR_NO_YES === intval($val)) $setDefault = true;
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'tppd_default='.intval($val);
                    break;
                case PayTplAddDTO::_first:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'tppd_first='.intval($val);
                    break;
            }
        }
        if(strlen($setString) < 1) return 0;
        $currTime       = CommTime::getTimeStamp(0);
        $isFail         = false;
        $sql            = 'INSERT INTO '.$this->DbAuto->getTableNameAll('tpl_paid_conf').' SET '.$setString.', tppd_delete=0, tppd_create_time='.$currTime.', tppd_update_time='.$currTime;
        $tppdId         = $this->DbAuto->getDataId($sql, $isFail);
        if($isFail || $tppdId < 1) return 0;
        $platform       = $setData[PayTplAddDTO::_platform]??0;
        $first          = $setData[PayTplAddDTO::_first]??0;
        if($setDefault) $this->updatePayTplDefault($tppdId, $platform, $first);
        return $tppdId;
    }

    /**
     * @param int $tppdId
     * @param array $setData
     * @param int $platformOld
     * @param int $firstOld
     * @return bool
     * payTplEdit
     */
    public function payTplEdit(int $tppdId, array $setData, int $platformOld, int $firstOld):bool
    {
        if($tppdId < 1 || count($setData) < 1) return false;
        $setString      = '';
        $setDefault     = false;
        foreach ($setData as $key => $val){
            switch ($key){
                case PayTplEditDTO::_platform:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'tppd_platform='.intval($val);
                    break;
                case PayTplEditDTO::_name:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'tppd_name=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case PayTplEditDTO::_pgspIdList:
                    if(!is_array($val) || count($val) < 1) return false;
                    $payGoodsList   = PayCtl::tag()->getPayGoodsSrcBatch($val);
                    if(count($payGoodsList) < 1) return false;
                    $psgpIdList     = array_map('intval', array_column($payGoodsList, 'pgsp_id'));
                    $psgpIdList     = array_values(array_intersect($val, $psgpIdList));
                    $pgspIdJson     = CommJson::encodeArray($psgpIdList);
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'pgsp_ids=\''.$this->DbAuto->getRealEscapeString($pgspIdJson).'\'';
                    break;
                case PayTplEditDTO::_defaultShow:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'tppd_default_show='.intval($val);
                    break;
                case PayTplEditDTO::_default:
                    if(YesOrNoEnum::YES_OR_NO_YES === intval($val)) $setDefault = true;
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'tppd_default='.intval($val);
                    break;
                case PayTplEditDTO::_first:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'tppd_first='.intval($val);
                    break;
            }
        }
        if(strlen($setString) < 1) return false;
        $isFail         = false;
        $currTime       = CommTime::getTimeStamp(0);
        $sql            = 'UPDATE '.$this->DbAuto->getTableNameAll('tpl_paid_conf').' SET '.$setString.', tppd_update_time='.$currTime.' WHERE tppd_id='.$tppdId.' AND tppd_delete=0';
        if($this->DbAuto->getDataNum($sql, $isFail) < 1 || $isFail) return false;
        $platform       = $setData[PayTplEditDTO::_platform]??$platformOld;
        $first          = $setData[PayTplEditDTO::_first]??$firstOld;
        if($setDefault) $this->updatePayTplDefault($tppdId, $platform, $first);
        return true;
    }

    /**
     * @param int $tppdId
     * @param int $platform
     * @param int $first
     * @return bool
     * updatePayTplDefault
     */
    public function updatePayTplDefault(int $tppdId, int $platform, int $first):bool
    {
        if($tppdId < 1 || !in_array($platform, [1, 2], true)) return false;
        $this->DbAuto->getDataNum('UPDATE '.$this->DbAuto->getTableNameAll('tpl_paid_conf').' SET tppd_default=0 WHERE tppd_id!='.$tppdId.' AND tppd_platform='.$platform.' AND tppd_first='.$first);
        return true;
    }
}